home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / DirectDraw / SwitchScreenMode / switchscreenmode.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-31  |  22.8 KB  |  675 lines

  1. //-----------------------------------------------------------------------------
  2. // File: SwitchScreenMode.cpp
  3. //
  4. // Desc: This sample demonstrates how to switch between windowed and
  5. //       full-screen exclusive DDraw cooperative levels.
  6. //
  7. // Copyright (c) 1999-2001 Microsoft Corporation. All rights reserved.
  8. //-----------------------------------------------------------------------------
  9. #define STRICT
  10. #include <windows.h>
  11. #include <ddraw.h>
  12. #include <mmsystem.h>
  13. #include "resource.h"
  14. #include "ddutil.h"
  15.  
  16.  
  17.  
  18.  
  19. //-----------------------------------------------------------------------------
  20. // Defines, constants, and global variables
  21. //-----------------------------------------------------------------------------
  22. #define SAFE_DELETE(p)  { if(p) { delete (p);     (p)=NULL; } }
  23. #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
  24.  
  25. #define SCREEN_WIDTH    640
  26. #define SCREEN_HEIGHT   480
  27. #define SCREEN_BPP      8
  28.  
  29. #define SPRITE_DIAMETER 48
  30. #define NUM_SPRITES     25
  31.  
  32. #define WINDOWED_HELPTEXT   TEXT("Press Escape to quit.  Press Alt-Enter to switch to Full-Screen mode.")
  33. #define FULLSCREEN_HELPTEXT TEXT("Press Escape to quit.  Press Alt-Enter to switch to Windowed mode.")
  34.  
  35. struct SPRITE_STRUCT
  36. {
  37.     FLOAT                fPosX; 
  38.     FLOAT                fPosY;
  39.     FLOAT                fVelX; 
  40.     FLOAT                fVelY;
  41. };
  42.  
  43. CDisplay*            g_pDisplay        = NULL;
  44. CSurface*            g_pLogoSurface    = NULL;  
  45. CSurface*            g_pTextSurface    = NULL;  
  46. RECT                 g_rcWindow;            
  47. RECT                 g_rcViewport;          
  48. RECT                 g_rcScreen;            
  49. BOOL                 g_bWindowed   = TRUE;  
  50. BOOL                 g_bActive     = FALSE;
  51. DWORD                g_dwLastTick;
  52. SPRITE_STRUCT        g_Sprite[NUM_SPRITES]; 
  53.  
  54.  
  55.  
  56.  
  57. //-----------------------------------------------------------------------------
  58. // Function-prototypes
  59. //-----------------------------------------------------------------------------
  60. LRESULT CALLBACK MainWndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );
  61. HRESULT WinInit( HINSTANCE hInst, int nCmdShow, HWND* phWnd, HACCEL* phAccel );
  62. HRESULT InitDirectDraw( HWND hWnd );
  63. VOID    FreeDirectDraw();
  64. HRESULT InitDirectDrawMode( HWND hWnd, BOOL bWindowed );
  65. HRESULT ProcessNextFrame( HWND hWnd );
  66. VOID    UpdateSprite( SPRITE_STRUCT* pSprite, FLOAT fTimeDelta );
  67. HRESULT DisplayFrame();
  68. HRESULT RestoreSurfaces();
  69.  
  70.  
  71.  
  72.  
  73. //-----------------------------------------------------------------------------
  74. // Name: WinMain()
  75. // Desc: Entry point to the program. Initializes everything and calls
  76. //       UpdateFrame() when idle from the message pump.
  77. //-----------------------------------------------------------------------------
  78. int APIENTRY WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, int nCmdShow )
  79. {
  80.     MSG       msg;
  81.     HWND   hWnd;
  82.     HACCEL hAccel;
  83.  
  84.     ZeroMemory( &g_Sprite, sizeof(SPRITE_STRUCT) * NUM_SPRITES );
  85.     srand( GetTickCount() );
  86.  
  87.     if( FAILED( WinInit( hInst, nCmdShow, &hWnd, &hAccel ) ) )
  88.         return FALSE;
  89.  
  90.     if( FAILED( InitDirectDraw( hWnd ) ) )
  91.     {
  92.         MessageBox( hWnd, TEXT("DirectDraw init failed. ")
  93.                     TEXT("The sample will now exit. "), TEXT("DirectDraw Sample"), 
  94.                     MB_ICONERROR | MB_OK );
  95.         return FALSE;
  96.     }
  97.  
  98.     g_dwLastTick = timeGetTime();
  99.  
  100.     while( TRUE )
  101.     {
  102.         // Look for messages, if none are found then 
  103.         // update the state and display it
  104.         if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
  105.         {
  106.             if( 0 == GetMessage(&msg, NULL, 0, 0 ) )
  107.             {
  108.                 // WM_QUIT was posted, so exit
  109.                 return (int)msg.wParam;
  110.             }
  111.  
  112.             // Translate and dispatch the message
  113.             if( 0 == TranslateAccelerator( hWnd, hAccel, &msg ) )
  114.             {
  115.                 TranslateMessage( &msg ); 
  116.                 DispatchMessage( &msg );
  117.             }
  118.         }
  119.         else
  120.         {
  121.             if( g_bActive )
  122.             {
  123.                 // Move the sprites, blt them to the back buffer, then 
  124.                 // flip or blt the back buffer to the primary buffer
  125.                 if( FAILED( ProcessNextFrame( hWnd ) ) )
  126.                 {
  127.                     SAFE_DELETE( g_pDisplay );
  128.  
  129.                     MessageBox( hWnd, TEXT("Displaying the next frame failed. ")
  130.                                 TEXT("The sample will now exit. "), TEXT("DirectDraw Sample"), 
  131.                                 MB_ICONERROR | MB_OK );
  132.                     return FALSE;
  133.                 }
  134.             }
  135.             else
  136.             {
  137.                 // Go to sleep if we have nothing else to do
  138.                 WaitMessage();
  139.  
  140.                 // Ignore time spent inactive 
  141.                 g_dwLastTick = timeGetTime();
  142.             }
  143.         }
  144.     }
  145. }
  146.  
  147.  
  148.  
  149.  
  150. //-----------------------------------------------------------------------------
  151. // Name: WinInit()
  152. // Desc: Init the window
  153. //-----------------------------------------------------------------------------
  154. HRESULT WinInit( HINSTANCE hInst, int nCmdShow, HWND* phWnd, HACCEL* phAccel )
  155. {
  156.     WNDCLASSEX wc;
  157.     HWND       hWnd;
  158.     HACCEL     hAccel;
  159.  
  160.     // Register the window class
  161.     wc.cbSize        = sizeof(wc);
  162.     wc.lpszClassName = TEXT("SwitchScreenMode");
  163.     wc.lpfnWndProc   = MainWndProc;
  164.     wc.style         = CS_VREDRAW | CS_HREDRAW;
  165.     wc.hInstance     = hInst;
  166.     wc.hIcon         = LoadIcon( hInst, MAKEINTRESOURCE(IDI_MAIN_ICON) );
  167.     wc.hIconSm       = LoadIcon( hInst, MAKEINTRESOURCE(IDI_MAIN_ICON) );
  168.     wc.hCursor       = LoadCursor( NULL, IDC_ARROW );
  169.     wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
  170.     wc.lpszMenuName  = MAKEINTRESOURCE(IDR_MENU);
  171.     wc.cbClsExtra    = 0;
  172.     wc.cbWndExtra    = 0;
  173.  
  174.     if( RegisterClassEx( &wc ) == 0 )
  175.         return E_FAIL;
  176.  
  177.     // Load keyboard accelerators
  178.     hAccel = LoadAccelerators( hInst, MAKEINTRESOURCE(IDR_MAIN_ACCEL) );
  179.  
  180.     // Calculate the proper size for the window given a client of 640x480
  181.     DWORD dwFrameWidth    = GetSystemMetrics( SM_CXSIZEFRAME );
  182.     DWORD dwFrameHeight   = GetSystemMetrics( SM_CYSIZEFRAME );
  183.     DWORD dwMenuHeight    = GetSystemMetrics( SM_CYMENU );
  184.     DWORD dwCaptionHeight = GetSystemMetrics( SM_CYCAPTION );
  185.     DWORD dwWindowWidth   = SCREEN_WIDTH  + dwFrameWidth * 2;
  186.     DWORD dwWindowHeight  = SCREEN_HEIGHT + dwFrameHeight * 2 + 
  187.                             dwMenuHeight + dwCaptionHeight;
  188.  
  189.     // Create and show the main window
  190.     DWORD dwStyle = WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX;
  191.     hWnd = CreateWindowEx( 0, TEXT("SwitchScreenMode"), 
  192.                            TEXT("DirectDraw SwitchScreenMode Sample"),
  193.                            dwStyle, CW_USEDEFAULT, CW_USEDEFAULT,
  194.                              dwWindowWidth, dwWindowHeight, NULL, NULL, hInst, NULL );
  195.     if( hWnd == NULL )
  196.         return E_FAIL;
  197.  
  198.     ShowWindow( hWnd, nCmdShow );
  199.     UpdateWindow( hWnd );
  200.  
  201.     // Save the window size/pos for switching modes
  202.     GetWindowRect( hWnd, &g_rcWindow );
  203.  
  204.     *phWnd   = hWnd;
  205.     *phAccel = hAccel;
  206.  
  207.     return S_OK;
  208. }
  209.  
  210.  
  211.  
  212.  
  213. //-----------------------------------------------------------------------------
  214. // Name: InitDirectDraw()
  215. // Desc: Create the DirectDraw object, and init the surfaces
  216. //-----------------------------------------------------------------------------
  217. HRESULT InitDirectDraw( HWND hWnd )
  218. {
  219.     HRESULT hr;
  220.  
  221.     // Initialize all the surfaces we need
  222.     if( FAILED( hr = InitDirectDrawMode( hWnd, g_bWindowed ) ) )
  223.         return hr;
  224.  
  225.     return S_OK;
  226. }
  227.  
  228.  
  229.  
  230.  
  231. //-----------------------------------------------------------------------------
  232. // Name: InitDirectDrawMode()
  233. // Desc: Called when the user wants to toggle between full-screen and windowed 
  234. //       to create all the needed DDraw surfaces and set the coop level
  235. //-----------------------------------------------------------------------------
  236. HRESULT InitDirectDrawMode( HWND hWnd, BOOL bWindowed )
  237. {
  238.     HRESULT                hr;
  239.     LPDIRECTDRAWPALETTE pDDPal   = NULL; 
  240.     int                 iSprite;
  241.  
  242.     // Release all existing surfaces
  243.     SAFE_DELETE( g_pLogoSurface );
  244.     SAFE_DELETE( g_pTextSurface );
  245.     SAFE_DELETE( g_pDisplay );
  246.  
  247.     // The back buffer and primary surfaces need to be created differently 
  248.     // depending on if we are in full-screen or windowed mode
  249.     g_pDisplay = new CDisplay();
  250.  
  251.     if( bWindowed )
  252.     {
  253.         if( FAILED( hr = g_pDisplay->CreateWindowedDisplay( hWnd, SCREEN_WIDTH, 
  254.                                                             SCREEN_HEIGHT ) ) )
  255.             return hr;
  256.  
  257.         // Add the system menu to the window's style
  258.         DWORD dwStyle = GetWindowLong( hWnd, GWL_STYLE );
  259.         dwStyle |= WS_SYSMENU;
  260.         SetWindowLong( hWnd, GWL_STYLE, dwStyle );
  261.  
  262.         // Show the menu in windowed mode 
  263. #ifdef _WIN64
  264.         HINSTANCE hInst = (HINSTANCE) GetWindowLongPtr( hWnd, GWLP_HINSTANCE );
  265. #else
  266.         HINSTANCE hInst = (HINSTANCE) GetWindowLong( hWnd, GWL_HINSTANCE );
  267. #endif
  268.         HMENU hMenu = LoadMenu( hInst, MAKEINTRESOURCE( IDR_MENU ) );
  269.         SetMenu( hWnd, hMenu );
  270.     }
  271.     else
  272.     {
  273.         if( FAILED( hr = g_pDisplay->CreateFullScreenDisplay( hWnd, SCREEN_WIDTH, 
  274.                                                               SCREEN_HEIGHT, SCREEN_BPP ) ) )
  275.         {
  276.             MessageBox( hWnd, TEXT("This display card does not support 640x480x8. "),
  277.                         TEXT("DirectDraw Sample"), MB_ICONERROR | MB_OK );
  278.             return hr;
  279.         }
  280.  
  281.         // Disable the menu in full-screen since we are 
  282.         // using a palette and a menu would look bad 
  283.         SetMenu( hWnd, NULL );
  284.  
  285.         // Remove the system menu from the window's style
  286.         DWORD dwStyle = GetWindowLong( hWnd, GWL_STYLE );
  287.         dwStyle &= ~WS_SYSMENU;
  288.         SetWindowLong( hWnd, GWL_STYLE, dwStyle );       
  289.     }
  290.  
  291.     // We need to release and re-load, and set the palette again to 
  292.     // redraw the bitmap on the surface.  Otherwise, GDI will not 
  293.     // draw the bitmap on the surface with the right palette
  294.     if( FAILED( hr = g_pDisplay->CreatePaletteFromBitmap( &pDDPal, MAKEINTRESOURCE( IDB_DIRECTX ) ) ) )
  295.         return hr;
  296.  
  297.     g_pDisplay->SetPalette( pDDPal );
  298.  
  299.     SAFE_RELEASE( pDDPal );
  300.  
  301.     if( g_bWindowed )
  302.     {
  303.         // Create a surface, and draw text to it.  
  304.         if( FAILED( hr = g_pDisplay->CreateSurfaceFromText( &g_pTextSurface, NULL, WINDOWED_HELPTEXT, 
  305.                                                             RGB(0,0,0), RGB(255, 255, 0) ) ) )
  306.             return hr;
  307.     }
  308.     else
  309.     {
  310.         // Create a surface, and draw text to it.  
  311.         if( FAILED( hr = g_pDisplay->CreateSurfaceFromText( &g_pTextSurface, NULL, FULLSCREEN_HELPTEXT, 
  312.                                                             RGB(0,0,0), RGB(255, 255, 0) ) ) )
  313.             return hr;
  314.     }
  315.  
  316.  
  317.     // Create a surface, and draw a bitmap resource on it.  The surface must 
  318.     // be newly created every time the screen mode is switched since it 
  319.     // uses the pixel format of the primary surface
  320.     if( FAILED( hr = g_pDisplay->CreateSurfaceFromBitmap( &g_pLogoSurface, MAKEINTRESOURCE( IDB_DIRECTX ), 
  321.                                                           SPRITE_DIAMETER, SPRITE_DIAMETER ) ) )
  322.         return hr;
  323.  
  324.     // Set the color key for the logo sprite to black
  325.     if( FAILED( hr = g_pLogoSurface->SetColorKey( 0 ) ) )
  326.         return hr;
  327.  
  328.     // Init all the sprites.  All of these sprites look the same, 
  329.     // using the g_pDDSLogo surface. 
  330.     for( iSprite = 0; iSprite < NUM_SPRITES; iSprite++ )
  331.     {
  332.         // Set the sprite's position and velocity
  333.         g_Sprite[iSprite].fPosX = (float) (rand() % SCREEN_WIDTH);
  334.         g_Sprite[iSprite].fPosY = (float) (rand() % SCREEN_HEIGHT); 
  335.  
  336.         g_Sprite[iSprite].fVelX = 500.0f * rand() / RAND_MAX - 250.0f;
  337.         g_Sprite[iSprite].fVelY = 500.0f * rand() / RAND_MAX - 250.0f;
  338.     }
  339.  
  340.     return S_OK;
  341. }
  342.  
  343.  
  344.  
  345.  
  346. //-----------------------------------------------------------------------------
  347. // Name: FreeDirectDraw()
  348. // Desc: Release all the DirectDraw objects
  349. //-----------------------------------------------------------------------------
  350. VOID FreeDirectDraw()
  351. {
  352.     SAFE_DELETE( g_pLogoSurface );
  353.     SAFE_DELETE( g_pTextSurface );
  354.     SAFE_DELETE( g_pDisplay );
  355. }
  356.  
  357.  
  358.  
  359.  
  360. //-----------------------------------------------------------------------------
  361. // Name: MainWndProc()
  362. // Desc: The main window procedure
  363. //-----------------------------------------------------------------------------
  364. LRESULT CALLBACK MainWndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
  365. {
  366.     switch (msg)
  367.     {
  368.         case WM_COMMAND:
  369.             switch( LOWORD(wParam) )
  370.             {
  371.                 case IDM_TOGGLEFULLSCREEN:
  372.                     // Toggle the fullscreen/window mode
  373.                     if( g_bWindowed )
  374.                         GetWindowRect( hWnd, &g_rcWindow );
  375.  
  376.                     g_bWindowed = !g_bWindowed;
  377.  
  378.                     if( FAILED( InitDirectDrawMode( hWnd, g_bWindowed ) ) )
  379.                     {
  380.                         SAFE_DELETE( g_pDisplay );
  381.  
  382.                         MessageBox( hWnd, TEXT("InitDirectDraw() failed. ")
  383.                                     TEXT("The sample will now exit. "), TEXT("DirectDraw Sample"), 
  384.                                     MB_ICONERROR | MB_OK );
  385.                         PostMessage( hWnd, WM_CLOSE, 0, 0 );
  386.                     }
  387.  
  388.                     return 0L;
  389.  
  390.                 case IDM_EXIT:
  391.                     // Received key/menu command to exit app
  392.                     PostMessage( hWnd, WM_CLOSE, 0, 0 );
  393.                     return 0L;
  394.             }
  395.             break; // Continue with default processing
  396.  
  397.         case WM_GETMINMAXINFO:
  398.             {
  399.                 // Don't allow resizing in windowed mode.  
  400.                 // Fix the size of the window to 640x480 (client size)
  401.                 MINMAXINFO* pMinMax = (MINMAXINFO*) lParam;
  402.  
  403.                 DWORD dwFrameWidth    = GetSystemMetrics( SM_CXSIZEFRAME );
  404.                 DWORD dwFrameHeight   = GetSystemMetrics( SM_CYSIZEFRAME );
  405.                 DWORD dwMenuHeight    = GetSystemMetrics( SM_CYMENU );
  406.                 DWORD dwCaptionHeight = GetSystemMetrics( SM_CYCAPTION );
  407.  
  408.                 pMinMax->ptMinTrackSize.x = SCREEN_WIDTH  + dwFrameWidth * 2;
  409.                 pMinMax->ptMinTrackSize.y = SCREEN_HEIGHT + dwFrameHeight * 2 + 
  410.                                             dwMenuHeight + dwCaptionHeight;
  411.  
  412.                 pMinMax->ptMaxTrackSize.x = pMinMax->ptMinTrackSize.x;
  413.                 pMinMax->ptMaxTrackSize.y = pMinMax->ptMinTrackSize.y;
  414.             }
  415.             return 0L;
  416.  
  417.         case WM_MOVE:
  418.             // Retrieve the window position after a move.  
  419.             if( g_pDisplay )
  420.                 g_pDisplay->UpdateBounds();
  421.  
  422.             return 0L;
  423.  
  424.         case WM_SIZE:
  425.             // Check to see if we are losing our window...
  426.             if( SIZE_MAXHIDE==wParam || SIZE_MINIMIZED==wParam )
  427.                 g_bActive = FALSE;
  428.             else
  429.                 g_bActive = TRUE;
  430.  
  431.             if( g_pDisplay )
  432.                 g_pDisplay->UpdateBounds();
  433.             break;
  434.  
  435.         case WM_SETCURSOR:
  436.             // Hide the cursor if in fullscreen 
  437.             if( !g_bWindowed )
  438.             {
  439.                 SetCursor( NULL );
  440.                 return TRUE;
  441.             }
  442.             break; // Continue with default processing
  443.  
  444.         case WM_QUERYNEWPALETTE:
  445.             if( g_pDisplay && g_pDisplay->GetFrontBuffer() )            
  446.             {
  447.                 // If we are in windowed mode with a desktop resolution in 8 bit 
  448.                 // color, then the palette we created during init has changed 
  449.                 // since then.  So get the palette back from the primary 
  450.                 // DirectDraw surface, and set it again so that DirectDraw 
  451.                 // realises the palette, then release it again. 
  452.                 LPDIRECTDRAWPALETTE pDDPal = NULL; 
  453.                 g_pDisplay->GetFrontBuffer()->GetPalette( &pDDPal );
  454.                 g_pDisplay->GetFrontBuffer()->SetPalette( pDDPal );
  455.                 SAFE_RELEASE( pDDPal );
  456.             }
  457.             break;
  458.  
  459.         case WM_EXITMENULOOP:
  460.             // Ignore time spent in menu
  461.             g_dwLastTick = timeGetTime();
  462.             break;
  463.  
  464.         case WM_EXITSIZEMOVE:
  465.             // Ignore time spent resizing
  466.             g_dwLastTick = timeGetTime();
  467.             break;
  468.  
  469.         case WM_SYSCOMMAND:
  470.             // Prevent moving/sizing and power loss in fullscreen mode
  471.             switch( wParam )
  472.             {
  473.                 case SC_MOVE:
  474.                 case SC_SIZE:
  475.                 case SC_MAXIMIZE:
  476.                 case SC_MONITORPOWER:
  477.                     if( !g_bWindowed )
  478.                         return TRUE;
  479.             }
  480.             break;
  481.             
  482.         case WM_DESTROY:
  483.             // Cleanup and close the app
  484.             FreeDirectDraw();
  485.             PostQuitMessage( 0 );
  486.             return 0L;
  487.     }
  488.  
  489.     return DefWindowProc(hWnd, msg, wParam, lParam);
  490. }
  491.  
  492.  
  493.  
  494.  
  495. //-----------------------------------------------------------------------------
  496. // Name: ProcessNextFrame()
  497. // Desc: Move the sprites, blt them to the back buffer, then 
  498. //       flip or blt the back buffer to the primary buffer
  499. //-----------------------------------------------------------------------------
  500. HRESULT ProcessNextFrame( HWND hWnd )
  501. {
  502.     HRESULT hr;
  503.  
  504.     // Figure how much time has passed since the last time
  505.     DWORD dwCurrTick = timeGetTime();
  506.     DWORD dwTickDiff = dwCurrTick - g_dwLastTick;
  507.  
  508.     // Don't update if no time has passed 
  509.     if( dwTickDiff == 0 )
  510.         return S_OK; 
  511.  
  512.     g_dwLastTick = dwCurrTick;
  513.  
  514.     // Move the sprites according to how much time has passed
  515.     for( int iSprite = 0; iSprite < NUM_SPRITES; iSprite++ )
  516.         UpdateSprite( &g_Sprite[ iSprite ], dwTickDiff / 1000.0f );
  517.  
  518.     // Check the cooperative level before rendering
  519.     if( FAILED( hr = g_pDisplay->GetDirectDraw()->TestCooperativeLevel() ) )
  520.     {
  521.         switch( hr )
  522.         {
  523.             case DDERR_EXCLUSIVEMODEALREADYSET:
  524.             case DDERR_NOEXCLUSIVEMODE:
  525.                 // Do nothing because some other app has exclusive mode
  526.                 Sleep(10);
  527.                 return S_OK;
  528.  
  529.             case DDERR_WRONGMODE:
  530.                 // The display mode changed on us. Update the
  531.                 // DirectDraw surfaces accordingly
  532.                 return InitDirectDrawMode( hWnd, g_bWindowed );
  533.         }
  534.         return hr;
  535.     }
  536.  
  537.     // Display the sprites on the screen
  538.     if( FAILED( hr = DisplayFrame() ) )
  539.     {
  540.         if( hr != DDERR_SURFACELOST )
  541.             return hr;
  542.  
  543.         // The surfaces were lost so restore them 
  544.         RestoreSurfaces();
  545.     }
  546.  
  547.     return S_OK;
  548. }
  549.  
  550.  
  551.  
  552.  
  553. //-----------------------------------------------------------------------------
  554. // Name: UpdateSprite()
  555. // Desc: Move the sprite around and make it bounce based on how much time 
  556. //       has passed
  557. //-----------------------------------------------------------------------------
  558. VOID UpdateSprite( SPRITE_STRUCT* pSprite, FLOAT fTimeDelta )
  559. {    
  560.     // Update the sprite position
  561.     pSprite->fPosX += pSprite->fVelX * fTimeDelta;
  562.     pSprite->fPosY += pSprite->fVelY * fTimeDelta;
  563.  
  564.     // Clip the position, and bounce if it hits the edge
  565.     if( pSprite->fPosX < 0.0f )
  566.     {
  567.         pSprite->fPosX  = 0;
  568.         pSprite->fVelX = -pSprite->fVelX;
  569.     }
  570.  
  571.     if( pSprite->fPosX >= SCREEN_WIDTH - SPRITE_DIAMETER )
  572.     {
  573.         pSprite->fPosX = SCREEN_WIDTH - 1 - SPRITE_DIAMETER;
  574.         pSprite->fVelX = -pSprite->fVelX;
  575.     }
  576.  
  577.     if( pSprite->fPosY < 0 )
  578.     {
  579.         pSprite->fPosY = 0;
  580.         pSprite->fVelY = -pSprite->fVelY;
  581.     }
  582.  
  583.     if( pSprite->fPosY > SCREEN_HEIGHT - SPRITE_DIAMETER )
  584.     {
  585.         pSprite->fPosY = SCREEN_HEIGHT - 1 - SPRITE_DIAMETER;
  586.         pSprite->fVelY = -pSprite->fVelY;
  587.     }   
  588. }
  589.  
  590.  
  591.  
  592.  
  593. //-----------------------------------------------------------------------------
  594. // Name: DisplayFrame()
  595. // Desc: Blts a the sprites to the back buffer, then it blts or flips the 
  596. //       back buffer onto the primary buffer.
  597. //-----------------------------------------------------------------------------
  598. HRESULT DisplayFrame()
  599. {
  600.     HRESULT hr;
  601.  
  602.     // Fill the back buffer with black, ignoring errors until the flip
  603.     g_pDisplay->Clear( 0 );
  604.  
  605.     // Blt the help text on the backbuffer, ignoring errors until the flip
  606.     g_pDisplay->Blt( 10, 10, g_pTextSurface, NULL );
  607.  
  608.     // Blt all the sprites onto the back buffer using color keying,
  609.     // ignoring errors until the flip. Note that all of these sprites 
  610.     // use the same DirectDraw surface.
  611.     for( int iSprite = 0; iSprite < NUM_SPRITES; iSprite++ )
  612.     {
  613.         g_pDisplay->Blt( (DWORD)g_Sprite[iSprite].fPosX, 
  614.                          (DWORD)g_Sprite[iSprite].fPosY, 
  615.                          g_pLogoSurface, NULL );
  616.     }
  617.  
  618.     // Flip or blt the back buffer onto the primary buffer
  619.     if( FAILED( hr = g_pDisplay->Present() ) )
  620.         return hr;
  621.  
  622.     return S_OK;
  623. }
  624.  
  625.  
  626.  
  627.  
  628. //-----------------------------------------------------------------------------
  629. // Name: RestoreSurfaces()
  630. // Desc: Restore all the surfaces, and redraw the sprite surfaces.
  631. //-----------------------------------------------------------------------------
  632. HRESULT RestoreSurfaces()
  633. {
  634.     HRESULT hr;
  635.     LPDIRECTDRAWPALETTE  pDDPal = NULL; 
  636.  
  637.     if( FAILED( hr = g_pDisplay->GetDirectDraw()->RestoreAllSurfaces() ) )
  638.         return hr;
  639.  
  640.     // No need to re-create the surface, just re-draw it.
  641.     // We need to release and re-load, and set the palette again to 
  642.     if( FAILED( hr = g_pDisplay->CreatePaletteFromBitmap( &pDDPal, MAKEINTRESOURCE( IDB_DIRECTX ) ) ) )
  643.         return hr;
  644.  
  645.     g_pDisplay->SetPalette( pDDPal );
  646.  
  647.     SAFE_RELEASE( pDDPal );
  648.  
  649.     // No need to re-create the surface, just re-draw it.
  650.     if( FAILED( hr = g_pLogoSurface->DrawBitmap( MAKEINTRESOURCE( IDB_DIRECTX ),
  651.                                                  SPRITE_DIAMETER, SPRITE_DIAMETER ) ) )
  652.         return hr;
  653.  
  654.     if( g_bWindowed )
  655.     {
  656.         // No need to re-create the surface, just re-draw it.
  657.         if( FAILED( hr = g_pTextSurface->DrawText( NULL, WINDOWED_HELPTEXT, 
  658.                                                    0, 0, RGB(0,0,0), RGB(255, 255, 0) ) ) )
  659.             return hr;
  660.     }
  661.     else
  662.     {
  663.         // No need to re-create the surface, just re-draw it.
  664.         if( FAILED( hr = g_pTextSurface->DrawText( NULL, FULLSCREEN_HELPTEXT, 
  665.                                                    0, 0, RGB(0,0,0), RGB(255, 255, 0) ) ) )
  666.             return hr;
  667.     }
  668.  
  669.     return S_OK;
  670. }
  671.  
  672.  
  673.  
  674.  
  675.